#include "config.h"

#include <dirent.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdarg.h>

#define DBG_SUBSYS S_LIBSTORAGE

#include "sysy_lib.h"
#include "cache.h"
#include "get_version.h"
#include "cluster.h"
#include "lichstor.h"
#include "storage.h"
#include "metadata.h"
#include "configure.h"
#include "job_dock.h"
#include "chunk.h"
#include "ynet_rpc.h"
#include "net_global.h"
#include "ylog.h"
#include "dbg.h"

#define FD_RESERVED 3    /* skip fd 0 1 2 */
atable_t atable;

int filetable_init()
{
        int ret;

        atable = array_create_table(NULL, 32768);
        if (atable == NULL) {
                ret = ENOMEM;
                GOTO(err_ret, ret);
        }

        return 0;
err_ret:
        return ret;
}

int filetable_open(int *_fd, const fileid_t *_fid)
{
        int ret, fd;
        fileid_t *fid;

        ret = ymalloc((void **)&fid, sizeof(*fid));
        if (unlikely(ret))
                GOTO(err_ret, ret);

        *fid = *_fid;

        fd = array_table_insert_empty(atable, fid);
        if (fd < 0) {
                ret = -fd;
                GOTO(err_free, ret);
        }

        *_fd = fd + FD_RESERVED;

        return 0;
err_free:
        yfree((void **)&fid);
err_ret:
        return ret;
}

int filetable_get(int fd, fileid_t *_fid)
{
        int ret;
        fileid_t *fid;

        fid = array_table_find(atable, fd - FD_RESERVED, NULL);
        if (fid == NULL) {
                ret = ENOENT;
                GOTO(err_ret, ret);
        }

        *_fid = *fid;

        return 0;
err_ret:
        return ret;
}

int filetable_close(int fd)
{
        int ret;
        fileid_t *fid;

        ret = array_table_remove(atable, fd - FD_RESERVED, NULL, (void **)&fid);
        if (unlikely(ret)) {
                GOTO(err_ret, ret);
        }

        yfree((void **)&fid);

        return 0;
err_ret:
        return ret;
}
